package com.fangcang.directlink.service.impl;

import ch.qos.logback.core.util.DatePatternToRegexUtil;
import com.alibaba.fastjson.JSON;
import com.fangcang.common.IncrementDTO;
import com.fangcang.common.ResponseDTO;
import com.fangcang.common.enums.ChannelTypeEnum;
import com.fangcang.common.enums.ErrorCodeEnum;
import com.fangcang.common.enums.IncreaseTypeEnum;
import com.fangcang.common.util.DateUtil;
import com.fangcang.common.util.PropertyCopyUtil;
import com.fangcang.common.util.StringUtil;
import com.fangcang.directlink.domain.PriceInfo2DO;
import com.fangcang.directlink.domain.Quota2DO;
import com.fangcang.directlink.dto.SyncPriceInfoDTO;
import com.fangcang.directlink.dto.SyncQuotaStateDTO;
import com.fangcang.directlink.dto.SyncRatesAndRoomsRequestDTO;
import com.fangcang.directlink.dto.SyncRestrictDTO;
import com.fangcang.directlink.mapper.PriceInfo2Mapper;
import com.fangcang.directlink.mapper.Quota2Mapper;
import com.fangcang.directlink.service.SyncRatePlanService;
import com.fangcang.directlink.service.SyncRedisService;
import com.fangcang.product.domain.PricePlanDO;
import com.fangcang.product.domain.RestrictDO;
import com.fangcang.product.dto.IncreaseDTO;
import com.fangcang.product.dto.PricePlanDTO;
import com.fangcang.product.mapper.RestrictMapper;
import com.fangcang.product.request.PricePlanRequestDTO;
import com.fangcang.product.service.PricePlanService;
import com.sun.org.apache.regexp.internal.RE;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class SyncRatePlanServiceImpl implements SyncRatePlanService {

    @Autowired
    private PriceInfo2Mapper priceInfo2Mapper;

    @Autowired
    private Quota2Mapper quota2Mapper;

    @Autowired
    private RestrictMapper restrictMapper;

    @Autowired
    private SyncRedisService syncRedisService;

    @Autowired
    private PricePlanService pricePlanService;

    @Override
    public ResponseDTO saveRatesAndRooms(SyncRatesAndRoomsRequestDTO syncRatesAndRoomsRequestDTO) {

        ResponseDTO responseDTO = new ResponseDTO(ErrorCodeEnum.SUCCESS);
        StringBuffer failReason = new StringBuffer();

        Integer pricePlanId = syncRatesAndRoomsRequestDTO.getPricePlanId();
        String supplyCode = syncRatesAndRoomsRequestDTO.getSupplyCode();

        if (!CollectionUtils.isEmpty(syncRatesAndRoomsRequestDTO.getPriceInfoList())){
            try {
                this.savePrice(supplyCode,pricePlanId,syncRatesAndRoomsRequestDTO.getPriceInfoList());
            } catch (Exception e){
                log.error("同步价格异常，请求参数：{}", JSON.toJSONString(syncRatesAndRoomsRequestDTO),e);
                failReason.append("保存价格异常");
            }
        }

        if (CollectionUtils.isEmpty(syncRatesAndRoomsRequestDTO.getRoomStatusList())){
            try {

                this.saveQuota(supplyCode,pricePlanId,syncRatesAndRoomsRequestDTO.getRoomStatusList());
            } catch (Exception e){
                log.error("同步配额异常，请求参数：{}", JSON.toJSONString(syncRatesAndRoomsRequestDTO),e);
                failReason.append("保存配额异常");
            }
        }

        if (CollectionUtils.isEmpty(syncRatesAndRoomsRequestDTO.getRestrictDTOList())){
            try {

                this.saveRestrict(supplyCode,pricePlanId,syncRatesAndRoomsRequestDTO.getRestrictDTOList());
            } catch (Exception e){
                log.error("同步条款异常，请求参数：{}", JSON.toJSONString(syncRatesAndRoomsRequestDTO),e);
                failReason.append("保存条款异常");
            }
        }

        if (StringUtil.isValidString(failReason.toString())){
            responseDTO.setResult(0);
            responseDTO.setFailReason(failReason.toString());
        }

        log.info("同步价格房态结果：{}",JSON.toJSONString(responseDTO));
        return responseDTO;
    }

    @Override
    public ResponseDTO createRatePlan(PricePlanRequestDTO pricePlanRequestDTO) {
        ResponseDTO responseDTO = new ResponseDTO(ErrorCodeEnum.SUCCESS);

        //TODO 看看这里是否需要处理一些字段
        responseDTO = pricePlanService.saveOrUpdatePricePlan(pricePlanRequestDTO);

        return responseDTO;
    }

    @Override
    public ResponseDTO deleteRatePlan(PricePlanDO pricePlanDO) {
        ResponseDTO responseDTO = new ResponseDTO(ErrorCodeEnum.SUCCESS);
        responseDTO = pricePlanService.deletePricePlan(pricePlanDO);
        return responseDTO;
    }

    private void saveRestrict(String supplyCode,Integer pricePlanId, List<SyncRestrictDTO> restrictDTOList) {

        RestrictDO restrictDO = null;
        List<RestrictDO> addList = new ArrayList<>();
        List<RestrictDO> updateList = new ArrayList<>();

        for(SyncRestrictDTO syncRestrictDTO : restrictDTOList){
            restrictDO = PropertyCopyUtil.transfer(syncRestrictDTO,RestrictDO.class);
            restrictDO.setRatePlanId(pricePlanId);
            restrictDO.setCreator(supplyCode);
            restrictDO.setCreateTime(DateUtil.getCurrentDate());

            Integer restrictId = syncRedisService.getRestrictId(pricePlanId);
            if (null != restrictId && restrictId > 0){
                restrictDO.setId(restrictId);
                restrictDO.setModifier(supplyCode);
                restrictDO.setModifyDate(DateUtil.getCurrentDate());

                updateList.add(restrictDO);
            } else{
                addList.add(restrictDO);
            }

            if (!CollectionUtils.isEmpty(addList)){
                restrictMapper.insertList(addList);
                //TODO 保存关系到缓存
            }

            if (!CollectionUtils.isEmpty(updateList)){
                updateList.forEach(restrictDO1 -> restrictMapper.updateByPrimaryKeySelective(restrictDO1));
            }
        }

    }

    private void saveQuota(String supplyCode,Integer pricePlanId, List<SyncQuotaStateDTO> roomStatusList) {
        Quota2DO quota2DO = null;
        List<Quota2DO> addList = new ArrayList<>();
        List<Quota2DO> updateList = new ArrayList<>();

        for (SyncQuotaStateDTO syncQuotaStateDTO : roomStatusList){
            quota2DO = new Quota2DO();
            quota2DO.setQuotaaccountId(syncRedisService.getQuotaAccountId(pricePlanId));
            quota2DO.setSaleDate(syncQuotaStateDTO.getSaleDate());
            quota2DO.setQuotaNum(syncQuotaStateDTO.getQuotaNum());
            quota2DO.setOverDraft(syncQuotaStateDTO.getOverDraft());
            quota2DO.setQuotaState(syncQuotaStateDTO.getQuotaState());
            //供应端直连设置配额，其实是相当于是直接设置为，所以总配额跟着一起变动
            quota2DO.setAllQuotaNum(syncQuotaStateDTO.getQuotaNum());
            quota2DO.setCreator(supplyCode);
            quota2DO.setCreateTime(DateUtil.getCurrentDate());

            Integer quotaId = syncRedisService.getQuotaId(pricePlanId,syncQuotaStateDTO.getSaleDate());
            if (null != quotaId && quotaId > 0){
                quota2DO.setQuotaId(quotaId);
                quota2DO.setModifier(supplyCode);
                quota2DO.setModifyTime(DateUtil.getCurrentDate());
                updateList.add(quota2DO);
            } else{
                addList.add(quota2DO);
            }

            if (!CollectionUtils.isEmpty(addList)){
                quota2Mapper.insertList(addList);
                //TODO 保存关系到缓存
            }

            if (CollectionUtils.isEmpty(updateList)){
                updateList.forEach(quota2DO1 -> {quota2Mapper.updateByPrimaryKeySelective(quota2DO1);});
            }
        }
        
    }


    private void savePrice(String supplyCode,Integer pricePlanId, List<SyncPriceInfoDTO> priceInfoList) {

        PriceInfo2DO priceInfo2DO = null;
        List<PriceInfo2DO> addList = new ArrayList<PriceInfo2DO>();
        List<PriceInfo2DO> updateList = new ArrayList<PriceInfo2DO>();
        for (SyncPriceInfoDTO syncPriceInfoDTO : priceInfoList){
            priceInfo2DO = new PriceInfo2DO();
            priceInfo2DO.setPriceplanId(pricePlanId);
            priceInfo2DO.setSaleDate(syncPriceInfoDTO.getSaleDate());
            //单位分，转换成元
            priceInfo2DO.setBasePrice(new BigDecimal(syncPriceInfoDTO.getBasePrice()/100));

            //TODO 要获取各渠道的加幅规则，计算各渠道的售价，然后同时保存售价
            BigDecimal b2bPrice = getSalePrice(pricePlanId,syncPriceInfoDTO.getSaleDate(),syncPriceInfoDTO.getBasePrice(), ChannelTypeEnum.B2B);
            priceInfo2DO.setB2bSaleprice(b2bPrice);

            BigDecimal taobaoPrice = getSalePrice(pricePlanId,syncPriceInfoDTO.getSaleDate(),syncPriceInfoDTO.getBasePrice(), ChannelTypeEnum.TAOBAO);
            priceInfo2DO.setTaobaoSaleprice(taobaoPrice);

            BigDecimal ctripPrice = getSalePrice(pricePlanId,syncPriceInfoDTO.getSaleDate(),syncPriceInfoDTO.getBasePrice(), ChannelTypeEnum.CTRIP);
            priceInfo2DO.setB2bSaleprice(ctripPrice);


            priceInfo2DO.setCreator(supplyCode);
            priceInfo2DO.setCreateTime(DateUtil.getCurrentDate());
            Integer priceId = syncRedisService.getPriceId(pricePlanId,syncPriceInfoDTO.getSaleDate());
            if (null != priceId && priceId > 0){//TODO 保存关系到缓存
                priceInfo2DO.setPriceinfoId(priceId);
                priceInfo2DO.setModifier(supplyCode);
                priceInfo2DO.setModifyTime(DateUtil.getCurrentDate());
                updateList.add(priceInfo2DO);
            }
            else{
                addList.add(priceInfo2DO);
            }
        }

        if (!CollectionUtils.isEmpty(addList)){
            priceInfo2Mapper.insertList(addList);
            //TODO 保存关系到缓存
        }

        if (!CollectionUtils.isEmpty(updateList)){
            updateList.forEach(tempPriceInfo2DO -> priceInfo2Mapper.updateByPrimaryKey(tempPriceInfo2DO));
        }

    }

    private BigDecimal getSalePrice(Integer pricePlanId, Date saleDate, Integer basePrice, ChannelTypeEnum channel) {
        IncreaseDTO increaseDTO = syncRedisService.getIncreaseByChannel(pricePlanId,saleDate,channel.key);
        if (null == increaseDTO){
            log.info("价格计划{}，{}在渠道{}没有加幅。",pricePlanId,saleDate,channel.key);
            return null;
        }
        return calcSalePrice(basePrice,increaseDTO);
    }


    /**
     *
     * @param basePrice  底价，单位是分
     * @param increase
     * @return
     */
    private BigDecimal calcSalePrice(Integer basePrice, IncreaseDTO increase) {
        if (null == increase){
            log.info("加幅规则空，不计算价格");
            return null;
        }

        BigDecimal salePrice = null;
        IncreaseTypeEnum increaseTypeEnum = IncreaseTypeEnum.getEnumByKey(increase.getIncreaseType());
        switch (increaseTypeEnum){
            case PLUS:
                Double afterPlus = basePrice/100 + increase.getIncreaseAmount();
                salePrice = new BigDecimal(afterPlus);
                break;

            case MINUS:
                Double afterMinus = basePrice/100 - increase.getIncreaseAmount();
                salePrice = new BigDecimal(afterMinus);
                break;

            case MULTIPLY:
                Double afterMultiply = basePrice * increase.getIncreaseAmount() / 100;
                salePrice = new BigDecimal(afterMultiply);
                break;
        }

        return salePrice;
    }

}
